<html>
<head>
<title>[Xin Wei] PHP Web Calculator</title>
<style>
body{
	font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
	font-size: 13px;
	line-height: 18px;
	color: #333;
	background-color: gainsboro;
}
.container {
	margin-top:80px;
	margin-left:auto;
	margin-right:auto;	
	width: 940px;
	display: block;
}
.module {
	width: 500px;
	padding: 30px 0 0 0;
	margin: 50px auto 30px;
	background: white;
	text-align: center;
	border-bottom: 1px solid rgba(0, 0, 0, 0.18);
	-webkit-border-radius: 10px;
	-moz-border-radius: 10px;
	border-radius: 10px;
	-webkit-box-shadow: 0px 2px 10px 2px #999999;
	-moz-box-shadow: 0px 2px 10px 2px #999999;
	box-shadow: 0px 2px 10px 2px #999999;
}
h2 {
	font-weight: 400;
	letter-spacing: 0px;
	font-size: 26px;
	color: #222;
	margin: 1em 0 0.8em;
	line-height: 36px;
	font-family:"proxima nova","Helvetica Neue", Helvetica, Arial, sans-serif;
}
hr {
	margin: 20px 0;
	border: 0;
	border-top: 1px solid #DDD;
	border-bottom: 1px solid white;
}
p {
	font-size: 16px;
	color: #999;
	line-height: 1.5;
	margin: 0 0 1.2em;
}
.calculator {
	width: 320px;
	margin: 0 auto 15px;
}
.calculator input{
	font-size: 16px;
	color: black;
	padding: 0.8em 0.8em;
	box-shadow: inset 0 1px 1px #ddd;
	width: 80%;
	display: inline-block;
	color: #555555;
	border: 1px solid #cccccc;
	-webkit-border-radius: 3px;
	-moz-border-radius: 3px;
	border-radius: 3px;
}
input[type="submit"]{
	font-size: 16px;
	padding: 1em 0.8em;
	letter-spacing: 1px;
	width: 40%;
}
input:focus{
	border-color: rgba(82, 168, 236, 0.8);
	-webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);
	-moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);
	box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);
	outline: 0;
	outline: thin dotted \9;
}
/* 	The following button CSS codes are taken from Bootstrap: http://twitter.github.com/bootstrap/index.html
	Bootstrap is a project licensed under the Apache License v2.0 which allows for modifications, distribution, sharing, and usage of the following 		
	CSS codes. */
.btn {
	display: inline-block;
	*display: inline;
	/* IE7 inline-block hack */
	*zoom: 1;
	padding: 4px 10px 4px;
	margin-bottom: 0;
	font-size: 13px;
	line-height: 18px;
	color: #333333;
	text-align: center;
	text-shadow: 0 1px 1px rgba(255, 255, 255, 0.75);
	vertical-align: middle;
	background-color: #f5f5f5;
	background-image: -moz-linear-gradient(top, #ffffff, #e6e6e6);
	background-image: -ms-linear-gradient(top, #ffffff, #e6e6e6);
	background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#e6e6e6));
	background-image: -webkit-linear-gradient(top, #ffffff, #e6e6e6);
	background-image: -o-linear-gradient(top, #ffffff, #e6e6e6);
	background-image: linear-gradient(top, #ffffff, #e6e6e6);
	background-repeat: repeat-x;
	filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#e6e6e6', GradientType=0);
	border-color: #e6e6e6 #e6e6e6 #bfbfbf;
	border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
	filter: progid:dximagetransform.microsoft.gradient(enabled=false);
	border: 1px solid #cccccc;
	border-bottom-color: #b3b3b3;
	-webkit-border-radius: 4px;
	-moz-border-radius: 4px;
	border-radius: 4px;
	-webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);
	-moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);
	box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);
	cursor: pointer;
	*margin-left: .3em;
}
.btn:hover {
	color: #333333;
	text-decoration: none;
	background-color: #e6e6e6;
	background-position: 0 -15px;
	-webkit-transition: background-position 0.1s linear;
	-moz-transition: background-position 0.1s linear;
	-ms-transition: background-position 0.1s linear;
	-o-transition: background-position 0.1s linear;
	transition: background-position 0.1s linear;
}
.btn-success {
	text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
	color: #ffffff;
    background-color: #5bb75b;
    background-image: -moz-linear-gradient(top, #62c462, #51a351);
    background-image: -ms-linear-gradient(top, #62c462, #51a351);
    background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#51a351));
    background-image: -webkit-linear-gradient(top, #62c462, #51a351);
    background-image: -o-linear-gradient(top, #62c462, #51a351);
    background-image: linear-gradient(top, #62c462, #51a351);
    background-repeat: repeat-x;
    filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#62c462', endColorstr='#51a351', GradientType=0);
    border-color: #51a351 #51a351 #387038;
    border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
    filter: progid:dximagetransform.microsoft.gradient(enabled=false);
}
.btn-success:hover {
	text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
	color: #ffffff;
    background-color: #51a351;
}
</style>
</head>
<body>
<div class="container">
    <div class="module">
        <h2>PHP Web Calculator</h2>
        <p align="center">Designed by Xin Wei, Project 1A, CS 143, Spring 2012</p>
        <p align="center">Please enter an expression to evaluate.</p>
        <form action="<?php echo $_SERVER['PHP_SELF']?>" method="GET" id="calculatorForm">
            <div class="calculator">
                <input id="calculate" type="text" name="calculate" placeholder="Example: 10.5+20*3/25">
            </div>
            <input type="submit" value="Calculate" class="btn btn-success">
        </form> <br>
<?php
	// Trimming White Spaces
	if(isset($_GET['calculate']))
		$expression = str_replace(" ","",$_GET['calculate']);
	//Utility Helper Functions
	function errorChk($exp)
	{
		if($exp == "*" || $exp == "/" || $exp == "+" || $exp == "-"
		|| $exp === "0" || $exp === "1" || $exp == "2" || $exp == "3"
		|| $exp == "4" || $exp == "5" || $exp == "6" || $exp == "7"
		|| $exp == "8" || $exp == "9" || $exp == ".")
			return TRUE;
		else
			return FALSE;
	}
	function nextPos($exp, $curpos)
	{
		for($j=$curpos+1; $j < strlen($exp); $j++)
		{
			if($exp[$j]=="+"||$exp[$j]=="-"||$exp[$j]=="*"||$exp[$j]=="/")
			{
				return $j;
			}
			else if($j == strlen($exp)-1)
			{
				return strlen($exp);
			}
		}
	}
	
	//Error Checking
	$errorFlag = 0;
	for($i=0; $i < strlen($expression); $i++)
	{
		if(!errorChk($expression[$i]))
		{
			$errorFlag = 1;
			break;
		}
	}
	if($expression[0] == "+" ||$expression[0]=="*"||$expression[0]=="/"
	|| $expression[strlen($expression)-1] == "+" ||$expression[strlen($expression)-1]=="*"
	||$expression[strlen($expression)-1]=="/" || $expression[strlen($expression)-1]=="-")
		$errorFlag = 1;
	
	//Storing values into a php array, also do a bit of error checking as well
	if($expression!='' && $errorFlag===0)
	{
		$indexArr = array();
		$counter = 0;
		$op_pos = 0;
		$negativeNum = 0;
		for($i=0; $i < strlen($expression); $i++)
		{
			if($expression[$i]=="+"||$expression[$i]=="-"||$expression[$i]=="*"||$expression[$i]=="/")
			{
				if($expression[$i+1]=="+"||$expression[$i+1]=="*"||$expression[$i+1]=="/")
				{
					//Two consecutive operators in a row, with the exception of the negative sign
					$errorFlag = 1;
				}
				if($expression[$i]=="-" && $errorFlag=== 0)
				{
					//Check to see if it's a negative number
					if($expression[$i+1]=="-")
						$errorFlag = 1;
					else{
						if($i == 0)
							$negativeNum = 1;
						else if($expression[$i-1]=="+" || $expression[$i-1]=="*"||$expression[$i-1]=="/")
							$negativeNum = 1;}
				}
				if($negativeNum===1 && $errorFlag=== 0)
				{
					$indexArr[] = substr($expression, $counter, nextPos($expression, $i)-$counter);
					if(nextPos($expression, $i)!=strlen($expression))
						$indexArr[] = substr($expression,nextPos($expression, $i),1);	
					$counter = nextPos($expression, $i)+1;
					$i = nextPos($expression, $i)+1;
					$negativeNum = 0;
				}
				else if($errorFlag=== 0){
					$indexArr[] = substr($expression,$counter,$i-$counter);
					$indexArr[] = substr($expression,$i,1);
					$counter = $i + 1;
				}
			}
			if($i == strlen($expression)-1 && $negativeNum===0 && $errorFlag=== 0)
			{
				$indexArr[] = substr($expression,$counter,strlen($expression)-$counter);
			}
		}
		// Found * and /, Left Associative
		while(array_search("*",$indexArr)!==false && array_search("/", $indexArr)!==false && $errorFlag===0)
		{
			if(array_search("*",$indexArr) > array_search("/", $indexArr))
				$op_pos = array_search("/", $indexArr);
			else
				$op_pos = array_search("*",$indexArr);
			
			if($op_pos === 0 || $op_pos == count($indexArr)-1)
			{
				$errorFlag = 1;
				break;
			}
			else {
				$var1 = floatval($indexArr[$op_pos-1]);
				$var2 = floatval($indexArr[$op_pos+1]);
				switch($indexArr[$op_pos]){
					case '*': 
						$result = $var1 * $var2;
						break;
					case '/':
						if($indexArr[$op_pos+1] == '0')
							$result = "";
						else
							$result = $var1 / $var2;
						break;
				}
				$indexArr[$op_pos] = $result;
				unset($indexArr[$op_pos-1]);
				unset($indexArr[$op_pos+1]);
				$indexArr = array_values($indexArr);
			}
			
		}
		
		while(array_search("*",$indexArr)!==false && array_search("/", $indexArr)===false && $errorFlag===0)
		{
			$op_pos = array_search("*",$indexArr);
			if($op_pos === 0 || $op_pos == count($indexArr)-1)
			{
				$errorFlag = 1;
				break;
			}
			else {
				$var1 = floatval($indexArr[$op_pos-1]);
				$var2 = floatval($indexArr[$op_pos+1]);
				switch($indexArr[$op_pos]){
					case '*': 
						$result = $var1 * $var2;
						break;
					case '/':
						if($indexArr[$op_pos+1] == '0')
							$result = "";
						else
							$result = $var1 / $var2;
						break;
				}
				$indexArr[$op_pos] = $result;
				unset($indexArr[$op_pos-1]);
				unset($indexArr[$op_pos+1]);
				$indexArr = array_values($indexArr);
			}
		}
		while(array_search("/", $indexArr)!==false && array_search("*",$indexArr)===false && $errorFlag===0)
		{
			$op_pos = array_search("/", $indexArr);
			if($op_pos === 0 || $op_pos == count($indexArr)-1)
			{
				$errorFlag = 1;
				break;
			}
			else {
				$var1 = floatval($indexArr[$op_pos-1]);
				$var2 = floatval($indexArr[$op_pos+1]);
				switch($indexArr[$op_pos]){
					case '*': 
						$result = $var1 * $var2;
						break;
					case '/':
						if($indexArr[$op_pos+1] == '0')
							$result = "";
						else
							$result = $var1 / $var2;
						break;
				}
				$indexArr[$op_pos] = $result;
				unset($indexArr[$op_pos-1]);
				unset($indexArr[$op_pos+1]);
				$indexArr = array_values($indexArr);
			}
		}
		
		//Addition or Subtraction, left Associative
		while((array_search("+",$indexArr,true)!=false || array_search("-", $indexArr,TRUE)!=false) && $errorFlag=== 0)
		{
			$a_pos = array_search("+",$indexArr,true);
			$s_pos = array_search("-", $indexArr,true);
			if($a_pos === false)
				$op_pos = $s_pos;
			else if($s_pos === false)
				$op_pos = $a_pos;
			else {
				if($a_pos > $s_pos)
					$op_pos = $s_pos;
				else {
					$op_pos = $a_pos;
				}
			}
			
			if($op_pos === false || $op_pos == count($indexArr)-1)
			{
				$errorFlag = 1;
				break;
			}
			else {
				$var1 = floatval($indexArr[$op_pos-1]);
				$var2 = floatval($indexArr[$op_pos+1]);
				switch($indexArr[$op_pos]){
					case '+': 
						$result = $var1 + $var2;
						break;
					case '-':
						$result = $var1 - $var2;
						break;
				}
				$indexArr[$op_pos] = $result;
				unset($indexArr[$op_pos-1]);
				unset($indexArr[$op_pos+1]);
				$indexArr = array_values($indexArr);
			}
		}
		if($errorFlag=== 0)
		{
			?>
			<hr>
	        <h2>Results</h2>
	        <p align="center">
        	<?php
			echo $_GET['calculate'].' = ';
			echo $indexArr[0];
		}
	}
	if($errorFlag === 1)
	{
		?>
        <hr>
        <h2>Results</h2>
        <p align="center">
        <?php
		echo "Invalid Expression: ".$_GET['calculate']."<br />Please enter an expression containing numeric digits and the following symbols ONLY: {+ - * / .}";
	}
?></p>
    </div>
</div>
</body>
</html>